package cn.fj.hrm.controller;
import cn.fj.hrm.basic.util.JsonResult;
import cn.fj.hrm.basic.util.PageList;
import cn.fj.hrm.document.CourseDoc;
import cn.fj.hrm.query.CourseDocQuery;
import cn.fj.hrm.repostitory.CourseDocRepository;
import cn.fj.hrm.reslutmapper.HighlightResultMapper;
import cn.fj.hrm.vo.AggrTermsVo;
import cn.fj.hrm.vo.CourseJsonResult;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/search")
public class ElasticSearchController {

    @Autowired
    private CourseDocRepository courseDocRepository;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private HighlightResultMapper  highlightResultMapper;


    /**
     * 批量添加或者修改
     * @param courseDocList
     * @return
     */
    @PostMapping("/saveBatch")
    public JsonResult saveBatch(@RequestBody List<CourseDoc> courseDocList){
        courseDocRepository.saveAll(courseDocList);
        return JsonResult.me();
    }

    /**
     * 批量删除
     * @param ids
     * @return
     */
    @DeleteMapping("/deleteByIds")
    public JsonResult deleteByIds(@RequestBody List<Long> ids){
        for (Long id : ids) {
            courseDocRepository.deleteById(id);
        }
        return JsonResult.me();
    }
    /**
     * 搜索课程+高级查询+分页+排序
     * @param courseDocQuery
     * @return
     */
    @PostMapping("/queryCourses")
    public JsonResult queryCourses(@RequestBody CourseDocQuery courseDocQuery){
        //添加过滤条件【多个单分支语句动态添加：当前端传递的请求参数非空时才会添加过滤条件】
        //ES的搜索需要NativeSearchQueryBuilder
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //1.bool组合条件：包含查询与过滤
        BoolQueryBuilder query = new BoolQueryBuilder();
        //课程名称关键字搜索
        if(StringUtils.hasText(courseDocQuery.getKeyword())){
            query.filter().add(QueryBuilders.matchQuery("name", courseDocQuery.getKeyword()));
        }
        //课程类别id搜索
        if(courseDocQuery.getCourseTypeId() != null){
            query.filter().add(QueryBuilders.termQuery("courseTypeId",courseDocQuery.getCourseTypeId()));
        }
        if(StringUtils.hasText(courseDocQuery.getCourseTypeName())){
            query.filter().add(QueryBuilders.termQuery("courseTypeName", courseDocQuery.getCourseTypeName()));
        }
        //机构名称搜索
        if(StringUtils.hasText(courseDocQuery.getTenantName())){
            query.filter().add(QueryBuilders.termQuery("tenantName", courseDocQuery.getTenantName()));
        }
        //课程等级搜索
        if(StringUtils.hasText(courseDocQuery.getGradeName())){
            query.filter().add(QueryBuilders.termQuery("gradeName", courseDocQuery.getGradeName()));
        }
        //价格范围搜索
        if(courseDocQuery.getPriceMin() != null){
            query.filter().add(QueryBuilders.rangeQuery("price").gte(courseDocQuery.getPriceMin()));
        }
        if(courseDocQuery.getPriceMax() != null){
            query.filter().add(QueryBuilders.rangeQuery("price").lte(courseDocQuery.getPriceMax()));
        }
        builder.withQuery(query);

        //排序
        Sort.Direction direction = Sort.Direction.ASC;
        if("desc".equalsIgnoreCase(courseDocQuery.getOrderType())){
            direction = Sort.Direction.DESC;
        }
        String orderField = "price";
        if(StringUtils.hasText(courseDocQuery.getOrderField())){
            orderField = courseDocQuery.getOrderField();
        }
        Sort sort = new Sort(direction, orderField);
        //添加分页【当前页码是从0开始的】
        Pageable pageable = PageRequest.of(courseDocQuery.getPageNo()-1, courseDocQuery.getPageSize(), sort);
        builder.withPageable(pageable);

        //设置高亮显示
        HighlightBuilder.Field field = new HighlightBuilder.Field("name")
                //使用前后标签将name字段的值中与搜索关键字相同的文字包起来，就显示有红色加粗效果了
                .preTags("<font style='color:red;'><b>")     //前标签
                .postTags("</b></font>");                   //后标签
        builder.withHighlightFields(field);  //名字高亮

        //=============================聚合查询Begin========================
        //聚合查询，按照机构名字聚合，按照数量倒排
        builder.addAggregation(AggregationBuilders.terms("tenantNameAgg")
                .field("tenantName").order(Terms.Order.count(false)).size(20));
        //聚合查询，按照课程类型聚合，按照数量倒排
        builder.addAggregation(AggregationBuilders.terms("couseTypeAgg")
                .field("courseTypeName").order(Terms.Order.count(false)).size(20));

        //Page<CourseDoc> page = courseDocRepository.search(builder.build());
        //Page的子接口，扩展了功能
        AggregatedPage<CourseDoc> page = elasticsearchTemplate.queryForPage(builder.build(),
                CourseDoc.class, highlightResultMapper);

        //获取聚合查询的结果
        StringTerms tenantNameAggTerms = (StringTerms) page.getAggregation("tenantNameAgg");
        StringTerms couseTypeAggTerms = (StringTerms) page.getAggregation("couseTypeAgg");
        //把机构名字聚合，搜集成字符串里集合
        List<AggrTermsVo> tenantNames = tenantNameAggTerms.getBuckets().stream().map(
                bucket ->  new AggrTermsVo(bucket.getKeyAsString(),bucket.getDocCount())
        ).collect(Collectors.toList());
        List<AggrTermsVo> courseTypes = couseTypeAggTerms.getBuckets().stream().map(
                bucket ->  new AggrTermsVo(bucket.getKeyAsString(),bucket.getDocCount())
        ).collect(Collectors.toList());

        //封装成我们自己的分页工具对象
        PageList<CourseDoc> pageList = new PageList<>(page.getTotalElements(), page.getContent());

        CourseJsonResult jsonResult = CourseJsonResult.me();
        jsonResult.setData(pageList);
        jsonResult.setAggrTenantNames(tenantNames);
        jsonResult.setAggrCourseTypes(courseTypes);

        return jsonResult;
    }

}
